/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <string>
#include <functional>
#include <cstdint>
#include <thread>
#include <atomic>
#include <chrono>
#include "utils_noncopyable.h"
#include "utils_callback_list.h"

namespace El {
namespace Utils {

class TimeManager : public NoCopyable {
public:
    static TimeManager &GetInstance();

    TimeManager();
    ~TimeManager();

    // 启动时间同步
    void Start();

    // 停止时间同步
    void Stop();

    // 同步rtc时间到系统时间
    void SyncRtcToSystem();

    // 同步系统时间到rtc时间
    void SyncSystemToRtc();

    // 获取当前utc时间,单位微秒
    uint64_t GetCurrentUtc();

    // 获取单调递增时间,单位微秒
    // @return 从系统启动以来的单调递增微秒数,不受系统时间调整影响
    uint64_t GetMonotonicTime();

    // 设置当前utc时间,单位微秒
    // @param utcTime 要设置的时间
    void SetCurrentUtc(uint64_t utcTime);

    // 注册时间跳变回调，返回回调句柄
    // @param callback 回调函数，参数为跳变的秒数
    // @return 回调句柄，用于取消注册
    int32_t Register(std::function<void(int64_t)> callback);

    // 取消注册时间跳变回调
    // @param handle 注册时返回的句柄
    void Unregister(int32_t handle);

    // 设置最小时间跳变间隔(秒)
    void SetMinJumpInterval(int64_t seconds);

    // 获取最小时间跳变间隔(秒)
    int64_t GetMinJumpInterval() const;

private:
    // 启动时间跳变检测
    void StartJumpDetection();

    // 停止时间跳变检测
    void StopJumpDetection();

private:
    static constexpr int64_t DEFAULT_MIN_JUMP_INTERVAL = 2; // 默认最小跳变间隔(秒)

    std::atomic<bool> running_;
    std::thread detector_thread_;
    std::chrono::steady_clock::time_point last_jump_time_;
    int64_t min_jump_interval_;
    CallbackList<void, int64_t> jump_callbacks_; // 时间跳变回调列表

    void DetectorThread();
};

} // namespace Utils
} // namespace El